package com.yf.service.chat.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yf.base.IBaseEnum;
import com.yf.constants.AiConstants;
import com.yf.converter.manage.AiConversationConverter;
import com.yf.converter.manage.AiMaskConverter;
import com.yf.converter.manage.AiMessageConverter;
import com.yf.converter.manage.AiToolConverter;
import com.yf.exception.ServiceException;
import com.yf.model.ai.entity.AiConfig;
import com.yf.model.ai.entity.AiConversation;
import com.yf.model.ai.entity.AiConversationToolBinding;
import com.yf.model.ai.entity.AiMask;
import com.yf.model.ai.entity.AiMessage;
import com.yf.model.ai.entity.AiTool;
import com.yf.model.ai.enums.AiModelEnum;
import com.yf.model.ai.form.UserChatConfigForm;
import com.yf.model.ai.query.UserChatConversationPageQuery;
import com.yf.model.ai.query.UserChatMessagePageQuery;
import com.yf.model.ai.query.UserChatToolPageQuery;
import com.yf.model.ai.vo.UserChatConversationDetailVO;
import com.yf.model.ai.vo.UserChatConversationVO;
import com.yf.model.ai.vo.UserChatMaskVO;
import com.yf.model.ai.vo.UserChatMessageVO;
import com.yf.model.ai.vo.UserChatToolProviderVO;
import com.yf.model.ai.vo.UserChatToolVO;
import com.yf.result.ResultCode;
import com.yf.security.utils.SecurityUtil;
import com.yf.service.chat.IUserChatService;
import com.yf.service.manage.IAiConfigService;
import com.yf.service.manage.IAiConversationService;
import com.yf.service.manage.IAiConversationToolBindingService;
import com.yf.service.manage.IAiMaskService;
import com.yf.service.manage.IAiMessageService;
import com.yf.service.manage.impl.AiToolServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户AI聊天相关服务
 *
 * @author : YiFei
 * @since : 2025/7/12 11:38
 */
@Service
@RequiredArgsConstructor
public class UserChatServiceImpl implements IUserChatService {

    private final IAiConversationService aiConversationService;
    private final AiToolServiceImpl aiToolService;
    private final IAiMaskService aiMaskService;
    private final IAiMessageService aiMessageService;
    private final IAiConfigService aiConfigService;
    private final DeepSeekChatModel deepSeekChatModel;
    private final IAiConversationToolBindingService aiConversationToolBindingService;
    private final AiConversationConverter aiConversationConverter;
    private final AiMaskConverter aiMaskConverter;
    private final AiMessageConverter aiMessageConverter;
    private final AiToolConverter aiToolConverter;

    /**
     * 分页查询会话记录
     *
     * @param queryParams 分页查询参数
     * @return 分页数据
     */
    @Override
    public IPage<UserChatConversationVO> getAiConversationPage(UserChatConversationPageQuery queryParams) {
        // 固定查询 50 用户当前的会话
        queryParams.setPageSize(50);
        Page<AiConversation> page = aiConversationService.lambdaQuery()
                .eq(queryParams.getTitle() != null, AiConversation::getTitle, queryParams.getTitle())
                .isNotNull(AiConversation::getLastActiveTime)
                .eq(AiConversation::getUserId, SecurityUtil.getUserId())
                .page(queryParams.lambdaMpPage(AiConversation::getLastActiveTime, false));
        // 查询对应图标
        List<AiConversation> records = page.getRecords();
        Set<Integer> maskInfo = records.stream().map(AiConversation::getCurrentMaskId).collect(Collectors.toSet());
        Map<Integer, String> maskIconMap;
        // 填充面具图标
        if (!maskInfo.isEmpty()) {
            // 查询掩码信息
            maskIconMap = aiMaskService.lambdaQuery()
                    .in(AiMask::getId, maskInfo)
                    .list()
                    .stream()
                    .collect(Collectors.toMap(AiMask::getId, AiMask::getIcon));
        } else {
            maskIconMap = new HashMap<>();
        }

        // Page To Vo
        List<UserChatConversationVO> userChatConversationVOS = records.stream().map(item -> {
            UserChatConversationVO vo = aiConversationConverter.entity2ChatVo(item);
            vo.setIcon(maskIconMap.get(item.getCurrentMaskId()));
            return vo;
        }).toList();

        return new Page<UserChatConversationVO>()
                .setRecords(userChatConversationVOS)
                .setTotal(page.getTotal())
                .setCurrent(page.getCurrent())
                .setSize(page.getSize());
    }

    /**
     * 分页查询消息记录
     *
     * @param queryParams 分页查询参数
     * @return 分页数据
     */
    @Override
    public IPage<UserChatMessageVO> getAiMessagePage(UserChatMessagePageQuery queryParams) {
        // 查询用户全部消息 , TODO 待二期更改
        queryParams.setPageSize(Integer.MAX_VALUE);
        checkConversationIsCurrentUser(queryParams.getConversationId());
        Page<AiMessage> page = aiMessageService.lambdaQuery()
                .eq(queryParams.getConversationId() != null, AiMessage::getConversationId, queryParams.getConversationId())
                .page(queryParams.lambdaMpPage(AiMessage::getSendTime, true));
        return aiMessageConverter.page2userChatVO(page);
    }

    /**
     * 获取AI全部可用面具
     *
     * @param maskName 面具名称
     * @return 面具列表
     */
    @Override
    public List<UserChatMaskVO> getAllMasks(String maskName) {
        return aiMaskConverter.list2userChatVO(aiMaskService.lambdaQuery()
                .like(StringUtils.hasText(maskName), AiMask::getName, maskName)
                .list());
    }

    /**
     * 查询所有工具
     *
     * @param queryParams 分页查询参数
     * @return 分页数据
     */
    @Override
    public IPage<UserChatToolVO> getToolPage(UserChatToolPageQuery queryParams) {
        // 固定查询 30 条, 工具分页
        queryParams.setPageSize(30);
        Page<AiTool> page = aiToolService.lambdaQuery()
                .eq(AiTool::getIsActive, Boolean.TRUE)
                .eq(StringUtils.hasText(queryParams.getComponentType()), AiTool::getComponentType, queryParams.getComponentType())
                .like(StringUtils.hasText(queryParams.getName()), AiTool::getName, queryParams.getName())
                .like(StringUtils.hasText(queryParams.getProvider()), AiTool::getDescription, queryParams.getProvider())
                .page(queryParams.lambdaMpPage(AiTool::getCreateTime, false));

        return aiToolConverter.page2userChatPageVO(page);
    }

    /**
     * 会话绑定工具
     *
     * @param conversationId 会话Id
     * @param toolIds        工具Id集合
     * @return 是否绑定成功
     */
    @Override
    public boolean conversationBindTools(Long conversationId, Set<Integer> toolIds) {
        // 查询不出会话, 或者会话不属于当前用户, 则返回 false , 绑定失败
        checkConversationIsCurrentUser(conversationId);
        // 绑定会话
        return aiConversationToolBindingService.bindToolToConversation(conversationId, toolIds);
    }

    /**
     * 会话绑定面具
     *
     * @param conversationId 会话Id
     * @param maskId         面具Id
     * @return 是否绑定成功
     */
    @Override
    public boolean conversationBindMask(Long conversationId, Integer maskId) {
        // 查询不出会话, 或者会话不属于当前用户, 则返回 false , 绑定失败
        checkConversationIsCurrentUser(conversationId);

        if (maskId == null) {
            // 解绑面具
            aiConversationService.lambdaUpdate()
                    .eq(AiConversation::getId, conversationId)
                    .set(AiConversation::getCurrentMaskId, null)
                    .update();
            return true;
        }

        // 查询不到对应面具，返回 false
        if (!aiMaskService.lambdaQuery()
                .eq(AiMask::getId, maskId)
                .exists()) {
            return false;
        }
        // 绑定会话面具
        aiConversationService.lambdaUpdate()
                .eq(AiConversation::getId, conversationId)
                .set(AiConversation::getCurrentMaskId, maskId)
                .update();
        return true;
    }

    /**
     * 修改会话标题
     *
     * @param conversationId 会话Id
     * @param title          会话标题
     * @return 是否修改成功
     */
    @Override
    public Boolean updateConversationTitle(Long conversationId, String title) {
        // 查询不出会话, 或者会话不属于当前用户, 则返回 false , 修改失败
        checkConversationIsCurrentUser(conversationId);
        // 修改会话标题
        aiConversationService.lambdaUpdate()
                .eq(AiConversation::getId, conversationId)
                .set(AiConversation::getTitle, title)
                .update();
        return true;
    }

    /**
     * 删除会话
     *
     * @param conversationIds 会话Id集合
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public Boolean removeConversation(Set<Long> conversationIds) {
        // 如果会话中包含其他用户会话，则不允许删除
        if (conversationIds.isEmpty() || !aiConversationService.lambdaQuery()
                .in(AiConversation::getId, conversationIds)
                .eq(AiConversation::getUserId, SecurityUtil.getUserId())
                .exists()) {
            throw new ServiceException(ResultCode.AI_CONVERSATION_NOT_FOUND);
        }
        // 删除会话
        aiConversationService.lambdaUpdate()
                .in(AiConversation::getId, conversationIds)
                .remove();
        // 删除会话绑定的工具
        aiConversationToolBindingService.lambdaUpdate()
                .in(AiConversationToolBinding::getConversationId, conversationIds)
                .remove();
        // 删除会话聊天记录
        aiMessageService.lambdaUpdate()
                .in(AiMessage::getConversationId, conversationIds)
                .remove();
        // 删除会话配置
        aiConfigService.lambdaUpdate()
                .in(AiConfig::getConversationId, conversationIds)
                .remove();
        return true;
    }

    /**
     * 删除会话聊天消息
     *
     * @param messageId      聊天消息Id
     * @param conversationId 会话Id
     * @return 是否删除成功
     */
    @Override
    public boolean removeMessage(Long messageId, Long conversationId) {
        checkConversationIsCurrentUser(conversationId);
        aiMessageService.lambdaUpdate()
                .eq(AiMessage::getId, messageId)
                .eq(AiMessage::getConversationId, conversationId)
                .remove();
        return true;
    }

    /**
     * 查询会话详情
     *
     * @param conversationId 会话Id
     * @return 会话详情
     */
    @Override
    public UserChatConversationDetailVO getConversationDetail(Long conversationId) {
        // 查询会话是否属于用户
        checkConversationIsCurrentUser(conversationId);
        // 查询会话信息
        AiConversation aiConversation = aiConversationService.lambdaQuery()
                .eq(AiConversation::getId, conversationId)
                .one();

        // 查询配置信息
        AiConfig aiConfig = aiConfigService.lambdaQuery()
                .eq(AiConfig::getConversationId, conversationId)
                .one();
        if (aiConfig == null) {
            aiConfig = aiConfigService.lambdaQuery()
                    .eq(AiConfig::getIsDefault, Boolean.TRUE)
                    .one();
        }
        // 查询面具信息
        Integer currentMaskId = aiConversation.getCurrentMaskId();
        AiMask aiMask = currentMaskId == null ? null : aiMaskService.lambdaQuery()
                .eq(AiMask::getId, currentMaskId)
                .one();
        // 查询工具列表
        Set<Integer> tools = aiConversationToolBindingService.lambdaQuery()
                .eq(AiConversationToolBinding::getConversationId, conversationId)
                .list().stream().map(
                        AiConversationToolBinding::getToolId)
                .collect(Collectors.toSet());
        // 填充 VO 信息
        return UserChatConversationDetailVO.builder()
                .configInfo(UserChatConversationDetailVO.AiConfigInfoVO.builder()
                        .id(aiConfig.getId())
                        .temperature(aiConfig.getTemperature())
                        .model(aiConfig.getModel().getValue())
                        .build())
                .maskInfo(aiMask == null ? null : UserChatConversationDetailVO.AiMaskInfoVO.builder()
                        .id(aiMask.getId())
                        .name(aiMask.getName())
                        .icon(aiMask.getIcon())
                        .build())
                .conversationInfo(UserChatConversationDetailVO.AiConversationInfoVO.builder()
                        .id(aiConversation.getId())
                        .title(aiConversation.getTitle())
                        .build())
                .toolIds(tools)
                .build();
    }

    /**
     * 更新会话配置
     *
     * @param conversationId 会话Id
     * @param form           配置表单
     * @return 是否更新成功
     */
    @Override
    public Boolean updateConversationConfig(Long conversationId, UserChatConfigForm form) {
        // 查询会话是否属于用户
        checkConversationIsCurrentUser(conversationId);
        // 修改会话配置
        AiConfig aiConfig = aiConfigService.lambdaQuery()
                .eq(AiConfig::getConversationId, conversationId)
                .one();

        if (aiConfig == null) {
            // 如果没有配置，则创建新的配置
            aiConfig = AiConfig.builder()
                    .conversationId(conversationId)
                    .model(IBaseEnum.getEnumByValue(form.getModel(), AiModelEnum.class))
                    .temperature(form.getTemperature())
                    .isDefault(Boolean.FALSE)
                    .build();
            aiConfigService.save(aiConfig);
        } else {
            // 更新已有配置
            aiConfig.setModel(AiModelEnum.valueOf(form.getModel()));
            aiConfig.setTemperature(form.getTemperature());
            aiConfigService.updateById(aiConfig);
        }
        return true;
    }

    /**
     * 更新AI会话标题
     *
     * @param conversationId 会话Id
     * @return 更新后的标题
     */
    @Override
    public String updateAiConversationTitle(Long conversationId) {
        // 查询会话是否属于用户
        checkConversationIsCurrentUser(conversationId);
        // 查询会话前两条聊天信息
        List<AiMessage> list = aiMessageService.lambdaQuery()
                .eq(AiMessage::getConversationId, conversationId)
                .orderByDesc(AiMessage::getSendTime)
                .last("LIMIT 2")
                .list();
        // 生成标题
        String content = ChatClient.builder(deepSeekChatModel).build()
                .prompt(AiConstants.GEN_TITLE_MESSAGE_TEMPLATE.
                        formatted(list.get(0).getContent(), list.size() > 1 ? list.get(1).getContent() : ""))
                .system(AiConstants.TITLE_SYSTEM_PROMPT)
                .call().content();
        // 更新会话标题
        aiConversationService.lambdaUpdate()
                .eq(AiConversation::getId, conversationId)
                .set(AiConversation::getTitle, content)
                .update();
        return content;
    }

    /**
     * 获取草稿会话
     *
     * @return 草稿会话Id
     */
    @Override
    public Long getDraftConversations() {
        // 草稿一定是最晚创建的
        AiConversation aiConversation = aiConversationService.lambdaQuery()
                .select(AiConversation::getId)
                .eq(AiConversation::getUserId, SecurityUtil.getUserId())
                .orderByDesc(AiConversation::getCreateTime)
                .last("LIMIT 1").one();
        // 查找一个没有聊天记录的会话
        if (aiConversation != null && aiMessageService.lambdaQuery()
                .eq(AiMessage::getConversationId, aiConversation.getId())
                .count() == 0) {
            return aiConversation.getId();
        }
        // 如果没有草稿会话，则新建一个
        AiConversation newAiConversation = AiConversation.builder()
                .title("新会话")
                .userId(SecurityUtil.getUserId())
                .build();
        aiConversationService.save(newAiConversation);
        return newAiConversation.getId();
    }

    /**
     * 获取工具提供者
     *
     * @return 工具提供者列表
     */
    @Override
    public List<UserChatToolProviderVO> getToolProvider() {
        // 查询所有工具
        List<AiTool> aiTools = aiToolService.lambdaQuery()
                .select(AiTool::getId, AiTool::getProvider, AiTool::getProviderIcon)
                .eq(AiTool::getIsActive, Boolean.TRUE)
                .list();

        // 按provider分组并汇总
        Map<String, List<AiTool>> providerMap = aiTools.stream()
                .filter(tool -> tool.getProvider() != null)
                .collect(Collectors.groupingBy(AiTool::getProvider));

        // 取第一个工具的providerIcon
        return providerMap.entrySet().stream().map(entry -> {
            String provider = entry.getKey();
            List<AiTool> tools = entry.getValue();
            UserChatToolProviderVO vo = new UserChatToolProviderVO();
            vo.setProvider(provider);
            // 取第一个工具的providerIcon
            vo.setProviderIcon(tools.get(0).getProviderIcon());
            vo.setToolCount(tools.size());
            vo.setToolIds(tools.stream().map(AiTool::getId).collect(Collectors.toList()));
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 检查会话是否属于当前用户
     *
     * @param conversationId 会话ID
     */
    private void checkConversationIsCurrentUser(Long conversationId) {
        if (!aiConversationService.lambdaQuery()
                .eq(AiConversation::getId, conversationId)
                .eq(AiConversation::getUserId, SecurityUtil.getUserId())
                .exists()) {
            throw new ServiceException(ResultCode.AI_CONVERSATION_NOT_FOUND);
        }
    }
}
